<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title>虚拟列表</title>
		<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
		<style type="text/css">
			*{
				padding: 0;
				margin: 0;
			}
			html,body,#app{
				height: 100%;
				overflow: hidden;
			}
			.virtual-list{
				position: relative;
				height: 100%;
				overflow-y: auto;
				 -webkit-overflow-scrolling: touch;
			}
			.virtual-list-container{
				position: absolute;
				left: 0;
				top: 0;
				right: 0;
				width: 100%;
			}
			.virtual-scroll{
				 position: absolute;
				  left: 0;
				  top: 0;
				  right: 0;
				  z-index: -1;
			}
			.virtual-list-item{border-bottom: 1px solid #eee;box-sizing: border-box;text-align: center;}
		</style>
	</head>
	<body>
		<div id="app">
			
			<div class="virtual-list" ref="list" @scroll="handleScroll($event)">
				<div style="height:300px"></div>
				<div class="virtual-scroll" :style="{height:listHeight+'px'}"></div>
				<div class="virtual-list-container" :style="{transform:getTransfrom}">
					<div class="virtual-list-item" v-for="item in visibleData" :key="item.id" style="height:100px;line-height: 100px;">{{item.value}}</div>
				</div>
			</div>
		</div>
		<script src="vue.min.js"></script>
		<script type="text/javascript">
			var now = Date.now()
			var data = [];
			for(var i = 0;i<1000;i++){
				data.push({id:i,value:i})
			}
			var vm = new Vue({
				el:"#app",
				data:function(){
					return {
						// 列表数据
						listData:[],
						// 屏幕高度
						screenH:0,
						// 每项高度
						itemSize:100,
						// 偏移值
						offsetTop:0,
						// 开始索引
						start:0,
						// 结束索引
						end:null
					}
				},
				computed:{
					listHeight:function(){
						return this.listData.length*this.itemSize
					},
					getTransfrom:function(){
						return `translate3d(0,${this.offsetTop}px,0)`
					},
					visibleCount:function(){
						return Math.ceil(this.screenH/this.itemSize);
					},
					visibleData:function(){
						var listData = this.listData;
						var len = listData.length;
						var end =Math.min(this.end,len)
						return listData.slice(this.start,end)
					}
					
				},
				created:function() {
					
					
				},
				mounted:function() {
					// 1.初始化数据
					this.listData = data
					// 1.获取屏幕高度
					this.screenH = this.$refs.list.offsetHeight;
					// 2.设置索引
					this.start = 0;
					this.end = this.start + this.visibleCount;
					
				},
				methods:{
					handleScroll:function(){
						//当前滚动位置
						  let scrollTop = this.$refs.list.scrollTop;
						  //此时的开始索引
						  this.start = Math.floor(scrollTop / this.itemSize);
						  //此时的结束索引
						  this.end = this.start + this.visibleCount;
						  //此时的偏移量
						  this.offsetTop = scrollTop - (scrollTop % this.itemSize);
						
					}
				}
			})
		</script>
	</body>
</html>
